# math_server.py
import os.path
import os
import httpx
import pypandoc
from starlette.applications import Starlette
from starlette.routing import Mount, Host
from mcp.server.fastmcp import FastMCP
from typing import List
from utils import (setup_logging, get_after_week_ms, get_before_week_ms, get_today_end_ms,
                   get_today_zero_ms, timestamp_format, get_temp_documents_dir,
                   judge_relevant_news, format_milliseconds_to_date, format_news_info)
import time
from datetime import datetime
from uuid import uuid4

mcp = FastMCP("Info")
logger = setup_logging()


@mcp.tool()
async def fetch_news_info(query: str, start_time: str | None = None, end_time: str | None = None) -> dict:
    """
    根据用户输入的关键词，快速检索并获取与之相关的全部新闻列表，帮助用户高效地获取最新资讯，满足其对特定主题新闻的查询需求。
    Args:
        query: "用户输入关键词"
        start_time: 开始时间，格式必须为 "YYYY-MM-DD"，例如 "2025-01-01"
        end_time: 结束时间，格式必须为 "YYYY-MM-DD"，例如 "2025-01-01"

    Returns: 舆情新闻信息列表
    """
    if start_time is None:
        _start_time = get_before_week_ms()
        _end_time = get_today_end_ms()
    else:
        try:
            start_time_fmt = datetime.strptime(start_time, "%Y-%m-%d")
            # 转换为时间戳（以秒为单位）
            midnight_timestamp_seconds = start_time_fmt.timestamp()
            # 转换为毫秒数
            start_time_int = int(midnight_timestamp_seconds * 1000)
            _start_time = str(start_time_int)
        except ValueError:
            return {"result": "日期格式不正确，必须为 YYYY-MM-DD，例如 2025-01-01,请重新解析，或者请求用户重新输入"}

    if end_time is None:
        _end_time = get_today_end_ms()
        _start_time = get_before_week_ms()
    else:
        try:
            end_time_fmt = datetime.strptime(end_time, "%Y-%m-%d")
            # 转换为时间戳（以秒为单位）
            midnight_timestamp_seconds = end_time_fmt.timestamp()
            # 转换为毫秒数
            end_time_int = int(midnight_timestamp_seconds * 1000)
            _end_time = str(end_time_int)
        except ValueError:
            return {"result": "日期格式不正确，必须为 YYYY-MM-DD，例如 2025-01-01,请重新解析，或者请求用户重新输入"}

    if _end_time < _start_time:
        return {"result": "结束日期不能早于开始日期, 请重新解析，或者请求用户重新输入"}

    print(_start_time, _end_time)

    url = "http://192.168.211.9:8089/indexer/search"
    data = {
        "indexType": "DOCUMENT",
        "start": 0,
        "query": f"({query}) && (mediaType:xinwen)",
        "startTime": _start_time,
        "endTime": _end_time,
        "sortClause": [{"sortField": "createdAt", "order": "desc"}],
        "rows": 2000,
        "needDetailData": True
    }
    headers = {
        "Content-Type": "application/json"
    }

    timeout_config = httpx.Timeout(100.0, connect=200.0)

    news_list = dict()
    async with httpx.AsyncClient() as client:
        try:
            response = await client.post(url, json=data, headers=headers, timeout=timeout_config)
            response.raise_for_status()
            result = response.json()
            result = result["result"]
            for item in result:
                relevant = judge_relevant_news(query, item['title'])
                if relevant:
                    key = item['websiteName'] + '-' + format_milliseconds_to_date(int(item['createdAt']))
                    hit = news_list.get(key, [])
                    if len(hit) < 3:
                        hit.append(item)
                        news_list[key] = hit
            final = []
            for arr in news_list.values():
                final += arr
            return {'news': format_news_info(final)}
        except httpx.HTTPError as e:
            logger.error(f"HTTP error occurred: {e}")
            raise Exception(f"HTTP error occurred: {e}")
        except Exception as e:
            logger.error(f"An error occurred: {e}")
            raise Exception(f"An error occurred: {e}")


@mcp.tool()
async def fetch_blog_info(query: str, start_time: str | None = None, end_time: str | None = None) -> List:
    """
    根据用户输入的关键词，快速检索并获取与之相关的全部博客列表，满足其对特定主题博客的查询需求。

    Args:
        query: "用户输入关键词"
        start_time: 开始时间，毫秒
        end_time: 结束时间，毫秒

    Returns: 博客信息列表
    """
    if start_time is None:
        _start_time = get_before_week_ms()
        _end_time = get_today_end_ms()
    else:
        try:
            start_time_fmt = datetime.strptime(start_time, "%Y-%m-%d")
            # 转换为时间戳（以秒为单位）
            midnight_timestamp_seconds = start_time_fmt.timestamp()
            # 转换为毫秒数
            start_time_int = int(midnight_timestamp_seconds * 1000)
            _start_time = str(start_time_int)
        except ValueError:
            return {"result": "日期格式不正确，必须为 YYYY-MM-DD，例如 2025-01-01,请重新解析，或者请求用户重新输入"}

    if end_time is None:
        _end_time = get_today_end_ms()
        _start_time = get_before_week_ms()
    else:
        try:
            end_time_fmt = datetime.strptime(end_time, "%Y-%m-%d")
            # 转换为时间戳（以秒为单位）
            midnight_timestamp_seconds = end_time_fmt.timestamp()
            # 转换为毫秒数
            end_time_int = int(midnight_timestamp_seconds * 1000)
            _end_time = str(end_time_int)
        except ValueError:
            return {"result": "日期格式不正确，必须为 YYYY-MM-DD，例如 2025-01-01,请重新解析，或者请求用户重新输入"}

    if _end_time < _start_time:
        return {"result": "结束日期不能早于开始日期, 请重新解析，或者请求用户重新输入"}

    url = "http://192.168.211.9:8089/indexer/search"
    data = {
        "indexType": "MICRO_BLOG",
        "start": 0,
        "query": query,
        "startTime": _start_time,
        "endTime": _end_time,
        "sortClause": [{"sortField": "createdAt", "order": "desc"}],
        "rows": 1000,
        "needDetailData": True
    }
    headers = {
        "Content-Type": "application/json",
        "Accept": "application/json",
    }

    timeout_config = httpx.Timeout(100.0, connect=200.0)

    async with httpx.AsyncClient() as client:
        try:
            response = await client.post(url, json=data, headers=headers, timeout=timeout_config)
            response.raise_for_status()
            result = response.json()
            return result["result"]
        except httpx.HTTPError as e:
            logger.error(f"HTTP error occurred: {e}")
            return []
        except Exception as e:
            logger.error(f"An error occurred: {e}")
            return []


@mcp.tool()
async def fetch_news_number(query: str, start_time: str | None = None, end_time: str | None = None) -> dict | None:
    """
    根据关键词统计起始时间段内每天相关新闻数量统计
    Args:
        query: 用户查询
        start_time: 起始时间
        end_time: 结束时间

    Returns: 每天相关新闻数量统计, 如果该查询无相关新闻则返回 None
    """
    if start_time is None:
        _start_time = get_before_week_ms()
        _end_time = get_today_end_ms()
    else:
        try:
            start_time_fmt = datetime.strptime(start_time, "%Y-%m-%d")
            # 转换为时间戳（以秒为单位）
            midnight_timestamp_seconds = start_time_fmt.timestamp()
            # 转换为毫秒数
            start_time_int = int(midnight_timestamp_seconds * 1000)
            _start_time = str(start_time_int)
        except ValueError:
            return {"result": "日期格式不正确，必须为 YYYY-MM-DD，例如 2025-01-01,请重新解析，或者请求用户重新输入"}

    if end_time is None:
        _end_time = get_today_end_ms()
        _start_time = get_before_week_ms()
    else:
        try:
            end_time_fmt = datetime.strptime(end_time, "%Y-%m-%d")
            # 转换为时间戳（以秒为单位）
            midnight_timestamp_seconds = end_time_fmt.timestamp()
            # 转换为毫秒数
            end_time_int = int(midnight_timestamp_seconds * 1000)
            _end_time = str(end_time_int)
        except ValueError:
            return {"result": "日期格式不正确，必须为 YYYY-MM-DD，例如 2025-01-01,请重新解析，或者请求用户重新输入"}

    if _end_time < _start_time:
        return {"result": "结束日期不能早于开始日期, 请重新解析，或者请求用户重新输入"}

    print(_start_time, _end_time)

    url = "http://192.168.211.9:8089/indexer/range_facet"
    data = {
        "indexType": "DOCUMENT",
        "query": f"({query}) && (mediaType:xinwen)",
        "startTime": _start_time,
        "endTime": _end_time,
        "rangeFields": ["createdAt"],
        "gap": "+24HOURS",
        "dataType": "DOCUMENT"
    }
    headers = {
        "Content-Type": "application/json",
        "Accept": "application/json",
    }
    timeout_config = httpx.Timeout(100.0, connect=200.0)
    async with httpx.AsyncClient() as client:
        try:
            response = await client.post(url, json=data, headers=headers, timeout=timeout_config)
            response.raise_for_status()
            result = response.json()
            if result["numFound"] == 0:
                return None
            created_at = result["result"]["createdAt"]
            final_result = dict()
            for key, value in created_at.items():
                final_result[timestamp_format(int(key))] = value
            return {'data': final_result, 'type': 'chart', 'chatType': "bar_chart", "description": "新闻统计数据，不要生成图片"}
        except httpx.HTTPError as e:
            logger.error(f"HTTP error occurred: {e}")
            return {"result": "无法获取结果, 请检查输入参数是否正确"}
        except Exception as e:
            logger.error(f"An error occurred: {e}")
            return {"result": "无法获取结果, 请检查输入参数是否正确"}


@mcp.tool()
async def fetch_blog_number(query: str, start_time: str | None = None, end_time: str | None = None) -> dict | None:
    """
    根据关键词统计起始时间段内每天相关博客数量统计
    Args:
        query: 用户查询
        start_time: 起始时间
        end_time: 结束时间

    Returns: 每天相关博客数量统计, 如果该查询无相关博客则返回 None
    """
    if start_time is None:
        _start_time = get_before_week_ms()
        _end_time = get_today_end_ms()
    else:
        try:
            start_time_fmt = datetime.strptime(start_time, "%Y-%m-%d")
            # 转换为时间戳（以秒为单位）
            midnight_timestamp_seconds = start_time_fmt.timestamp()
            # 转换为毫秒数
            start_time_int = int(midnight_timestamp_seconds * 1000)
            _start_time = str(start_time_int)
        except ValueError:
            return {"result": "日期格式不正确，必须为 YYYY-MM-DD，例如 2025-01-01,请重新解析，或者请求用户重新输入"}

    if end_time is None:
        _end_time = get_today_end_ms()
        _start_time = get_before_week_ms()
    else:
        try:
            end_time_fmt = datetime.strptime(end_time, "%Y-%m-%d")
            # 转换为时间戳（以秒为单位）
            midnight_timestamp_seconds = end_time_fmt.timestamp()
            # 转换为毫秒数
            end_time_int = int(midnight_timestamp_seconds * 1000)
            _end_time = str(end_time_int)
        except ValueError:
            return {"result": "日期格式不正确，必须为 YYYY-MM-DD，例如 2025-01-01,请重新解析，或者请求用户重新输入"}

    if _end_time < _start_time:
        return {"result": "结束日期不能早于开始日期, 请重新解析，或者请求用户重新输入"}

    url = "http://192.168.211.9:8089/indexer/range_facet"
    data = {
        "query": query,
        "startTime": _start_time,
        "endTime": _end_time,
        "rangeFields": ["createdAt"],
        "gap": "+24HOURS",
        "dataType": "MICRO_BLOG"
    }

    headers = {
        "Content-Type": "application/json",
        "Accept": "application/json",
    }

    timeout_config = httpx.Timeout(100.0, connect=200.0)

    async with httpx.AsyncClient() as client:
        try:
            response = await client.post(url, json=data, headers=headers, timeout=timeout_config)
            response.raise_for_status()
            result = response.json()
            if result["numFound"] == 0:
                return None
            created_at = result["result"]["createdAt"]
            final_result = dict()
            for key, value in created_at.items():
                final_result[timestamp_format(int(key))] = value
            return {'data': final_result, 'type': 'chart', 'chatType': "bar_chart"}
        except httpx.HTTPError as e:
            logger.error(f"HTTP error occurred: {e}")
            return {"result": "无法获取结果, 请检查输入参数是否正确"}
        except Exception as e:
            logger.error(f"An error occurred: {e}")
            return {"result": "无法获取结果, 请检查输入参数是否正确"}


@mcp.tool()
async def markdown_to_word(markdown: str, docx_name: str):
    """
    将Markdown文本内容转成word文档
    Args:
        markdown: Markdown文本内容
        docx_name: 文件名称

    Returns: word文档路径
    """
    file_name = str(uuid4()) + ".docx"
    md_name = str(uuid4()) + ".md"
    destination_path = os.path.join(get_temp_documents_dir(), file_name)
    md_path = os.path.join(get_temp_documents_dir(), "markdown", md_name)
    # 将 Markdown 字符串转换为 Word 文件
    with open(md_path, "w", encoding="utf-8") as file:
        file.write(markdown)
    try:
        output = pypandoc.convert_file(
            md_path,
            "docx",
            outputfile=destination_path,
            extra_args=["--reference-doc=template.docx"]
        )
        if output == "":
            if os.path.exists(md_path):
                os.remove(md_path)
            return {"result": f"[{docx_name}]('http://192.168.201.123/documents/{file_name}')"}
        else:
            return {"result": "转换失败"}
    except Exception as e:
        logger.error(f"An error occurred: {e}")
        return {"result": "转换失败"}



# 挂载SSE服务器到ASGI服务器上
app = Starlette(
    routes=[
        Mount('/', app=mcp.sse_app()),
    ]
)

if __name__ == "__main__":
    import uvicorn
    uvicorn.run("news_server:app", host="0.0.0.0", port=5050)
